package com.eddie.linkedlist;

import lombok.NoArgsConstructor;

import java.util.Scanner;

public class SingleLinkedListDemo {

    public static void main(String[] args) {
        SingleLinkedList singleLinkedList = new SingleLinkedList();
        singleLinkedList.addByOrder(new HeroNode(4, "林冲", "豹子头"));
        singleLinkedList.addByOrder(new HeroNode(1, "宋江", "及时雨"));
        singleLinkedList.addByOrder(new HeroNode(2, "卢俊义", "玉麒麟"));
        singleLinkedList.addByOrder(new HeroNode(3, "吴用", "智多星"));
        singleLinkedList.updateNickname(new HeroNode(2, "卢俊义", "Eddie"));
        singleLinkedList.show();
/*        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入删除的编号：");
        singleLinkedList.delete(scanner.nextInt());
        singleLinkedList.show();*/
//        try {
//            System.out.println("\n找到的英雄");
//            System.out.println(findByReciprocalIndex(singleLinkedList.head, 3));
//        } catch (Exception e) {
//            System.out.println(e.getMessage());
//        }
        reverseLinkedList(singleLinkedList.head);
        singleLinkedList.show();
    }

    public static void reverseLinkedList(HeroNode head) {
        if (getLength(head) > 1) {
            HeroNode temp = head.next;
            HeroNode reverseHead = new HeroNode(0, "", "");
            HeroNode next;
            while (temp != null) {
                next = temp.next;//先暂时保存当前节点的下一个节点，因为后面要将当前的节点后移
                temp.next = reverseHead.next; //将temp的下一个节点指向新的链表的最前端
                reverseHead.next = temp;
                temp = next;//让temp后移
            }
            head.next = reverseHead.next;
            System.out.println();
        }
    }



    /**
     * 查找单链表中的倒数第k个节点【新浪面试题】
     */
    public static HeroNode findByReciprocalIndex(HeroNode head, int index) {
        int length = getLength(head);
        if (length != 0) {
            if (length < index) {
                throw new RuntimeException("链表长度不够");
            }
            int getIndex = length - index;
            int i = 0;
            HeroNode temp = head.next;
            while (temp != null) {
                if (i == getIndex) {
                    break;
                }
                i++;
                temp = temp.next;
            }
            return temp;
        }
        throw new RuntimeException("链表为空");
    }

    /**
     * 获取单链表节点的个数（如果是带头结点，需要不统计头节点）
     */
    public static int getLength(HeroNode head) {
        if (head.next == null) {
            return 0;
        }
        int length = 0;
        //定义一个辅助变量
        HeroNode cur = head.next;
        while (cur != null) {
            length++;
            //遍历
            cur = cur.next;
        }
        return length;
    }

}

/**
 * 定义SingleLinkedList 管理英雄
 */
class SingleLinkedList {
    //初始化一个头节点，头节点不动 不存放具体数据
    public final HeroNode head = new HeroNode(0, "", "");

    /**
     * 添加节点到单项链表
     * 思路：当不考虑编号的顺序时，
     * 1、找到当前链表的最后节点
     * 2、将最后这个节点的next指向新的节点
     */
    public void add(HeroNode node) {
        //因为head节点不能动，因此需要一个辅助变量temp
        HeroNode temp = head;
        //遍历链表找到
        while (temp.next != null) {
            //说明不是
            temp = temp.next;
        }
        //当退出while循环时，temp就指向了链表的最后
        temp.next = node;
    }

    public void addByOrder(HeroNode node) {
        HeroNode temp = head;
        //标识添加的编号是否存在
        boolean flag = false;
        //遍历链表找到
        while (temp.next != null) {
            //说明不是
            if (temp.next.no > node.no) {
                break;
            } else if (temp.next.no == node.no) {
                flag = true;
                break;
            }
            //后移，遍历当前链表
            temp = temp.next;
        }
        //判断flag
        if (flag) {
            //说明编号存在
            System.out.printf("准备插入的英雄编号 %d 已经存在，不能加入", node.no);
        } else {
            //插入到链表,temp的后面
            node.next = temp.next;
            temp.next = node;
        }
    }

    /**
     * 根据编号来修改英雄参数
     * 根据newHeroNode   no来修改
     */
    public void updateNickname(HeroNode newHeroNode) {
        //判断是否为空
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        HeroNode temp = head;
        boolean flag = false;
        while (temp.next != null) {
            if (temp.next.no == newHeroNode.no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.next.nickName = newHeroNode.nickName;
            temp.next.name = newHeroNode.name;
        } else {
            System.out.printf("没有找到编号为：%d 的节点，不能修改\n", newHeroNode.no);
        }
    }

    public void delete(int no) {
        //判断是否为空
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        HeroNode temp = head;
        boolean flag = false;
        while (temp.next != null) {
            if (temp.next.no == no) {
                flag = true;
                break;
            }
            temp = temp.next;
        }
        if (flag) {
            temp.next = temp.next.next;
        } else {
            System.out.printf("没有找到编号为：%d 的节点，不能删除\n", no);
        }
    }

    public void show() {
        //遍历链表找到
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        HeroNode temp = head.next;
        while (true) {
            if (temp != null) {
                System.out.println(temp);
                temp = temp.next;
            } else {
                break;
            }
        }
    }
}

@NoArgsConstructor
class HeroNode {
    public int no;
    public String name;
    public String nickName;
    public HeroNode next;
    //构造器

    public HeroNode(int no, String name, String nickName) {
        this.no = no;
        this.name = name;
        this.nickName = nickName;
    }

    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickName='" + nickName + '}';
    }
}
